home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 1997 September / Macworld (1997-09).dmg / Serious Software / Cherwell Scientific Demos / pro Fit / pro Fit 5.0 demo (fpu).sea / pro Fit 5.0 demo (fpu) / External Modules / External modules sources / C / Contour plotting / ContourData.c < prev    next >
Text File  |  1996-06-08  |  15KB  |  513 lines

  1.  
  2.  
  3. #include "proFit_interface.h"
  4.  
  5. #ifndef __MODULE_UTILITIES__
  6. #include "ModuleUtilities.h"
  7. #endif
  8. #ifndef __STRING_SUPPORT__
  9. #include "StringSupport.h"
  10. #endif
  11. #ifndef __CONTOUR_PLOTTER__
  12. #include "ContourPlotter.h"
  13. #endif
  14.  
  15. /* the following struct contains the variables that we use in Run() */
  16. /* We collect them into a struct such that we can pass them all simply */
  17. /* by passing a pointer to this struct */
  18.  
  19.  
  20. typedef struct
  21. {
  22.     double        firstLevel;                /* default values */
  23.     double        lastLevel;
  24.     double        levelStep;
  25.     long        x1Min, x1Max;            // range for x1
  26.     long        x2Min, x2Max;            // range for x2
  27.     Boolean        useCurrentGraph;        // true if we should draw into current graph
  28.     long        customContourWindow;    // 0 or ref to a custom contour level window 
  29.     long        customContourColumn;    // 0 or id of a custom contour column
  30. }MyStaticVars;
  31.  
  32.  
  33.  
  34.  
  35. /***************************************************************************************/
  36.  
  37. void SetUp (    short* const moduleKind,        /* return isFunction or isProgram */
  38.                 Str255 name,                    /* the name of the program of function */
  39.                                                 /*  (pascal string) */
  40.                 long* const requiredGlobals,    /* the number of bytes to be allocated */
  41.                                                 /*  in ExtModulesParamBlock.globals. */
  42.                                                 /* Set to 0 if you don't use this feature */
  43.                 ExtModulesParamBlock* pb)        /*     can be ignored in most cases */
  44.     /* called when your code resource is linked to proFit */
  45. {
  46.     *moduleKind=isProgram;                                /* we define a program */
  47.     SetPascalStr(name,"\pContour Plot Data...",255);    /* its name */
  48.     *requiredGlobals = sizeof(MyStaticVars);    /* our static vars */
  49. }
  50.  
  51.  
  52.  
  53. /***************************************************************************************/
  54.  
  55. void InitializeProg (ExtModulesParamBlock* pb)
  56.     /* Can be left emtpy if not needed. */
  57.     /* Only used by advanced programmers. */
  58.     /* called when the resource is linked to proFit after SetUp was called */
  59. {
  60.     MyStaticVars* vs = (MyStaticVars*)pb->globals;
  61.     vs->firstLevel = -1;                            // set default values
  62.     vs->lastLevel = 1;
  63.     vs->levelStep = 0.2;
  64.     vs->x1Min = 1;
  65.     vs->x1Max = 5;
  66.     vs->x2Min = 1;
  67.     vs->x2Max = 5;
  68.     vs->useCurrentGraph = true;
  69.     vs->customContourWindow = 0;
  70.     vs->customContourColumn = 0;
  71. }
  72.  
  73. /***************************************************************************************/
  74.  
  75. enum {
  76.     firstLevelTitleItem = 3,
  77.     lastLevelTitleItem,
  78.     distanceTitleItem,
  79.     firstLevelItem = 6,
  80.     lastLevelItem,
  81.     distanceItem,
  82.     dataWindowItem = 23,
  83.     x1FirstItem = 10,
  84.     x1LastItem = 11,
  85.     x2FirstItem = 14,
  86.     x2LastItem = 16,
  87.     useCurrentGraphItem = 17,
  88.     regularContourItem = 18,
  89.     customContourItem,
  90.     windowItem = 20,
  91.     columnItem,
  92.     helpButtonItem = 22
  93.     };
  94.  
  95.  
  96. static Boolean GetRow(DialogData* dlg, short itemID, long* const value)
  97. {
  98.     long    val;
  99.     long    nrRows = NrRows();
  100.  
  101.     if (MyGetLongItem(dlg, itemID, &val) == false) return false;
  102.     if (val < 1)
  103.     {    MySelectItemText(dlg, itemID, 0, 0x7FFF);
  104.         SysBeep(30);
  105.         return false;
  106.     }
  107.     if (val > nrRows) val = nrRows;
  108.  
  109.     *value = val;
  110.     return true;
  111. }
  112.  
  113. static Boolean GetColumn(DialogData* dlg, short itemID, long* const value)
  114. {
  115.     long    val;
  116.     long    nrCols = NrCols();
  117.  
  118.     if (MyGetLongItem(dlg, itemID, &val) == false) return false;
  119.     if (val < 1)
  120.     {    MySelectItemText(dlg, itemID, 0, 0x7FFF);
  121.         SysBeep(30);
  122.         return false;
  123.     }
  124.     if (val > nrCols) val = nrCols;
  125.  
  126.     *value = val;
  127.     return true;
  128. }
  129.  
  130.  
  131. static Boolean MyFunction(double x1, double x2, double* const x3, void* param)
  132. {
  133.     long    row = RoundDouble(x2);
  134.     long    col = RoundDouble(x1);
  135.  
  136.     if (TestData(row, col) == false) return false;
  137.     *x3 = GetData(row, col);
  138.     return true;
  139. }//MyFunction
  140.  
  141. static void ShowHideItems(DialogData* const dlg)
  142.     // shows and hides the items in the lower part of the dialog
  143. {
  144.     static const char regularItems[] = {firstLevelTitleItem, lastLevelTitleItem,
  145.             distanceTitleItem, firstLevelItem, lastLevelItem, distanceItem, 0};
  146.     static const char customItems[] = {windowItem, columnItem, 0};
  147.  
  148.     char*    itemsToShow;
  149.     char*    itemsToHide;
  150.  
  151.     if (MyGetItemValue(dlg, regularContourItem))
  152.     {    itemsToShow = (char*)regularItems;
  153.         itemsToHide = (char*)customItems;
  154.     }
  155.     else
  156.     {    itemsToShow = (char*)customItems;
  157.         itemsToHide = (char*)regularItems;
  158.     }
  159.     while (*itemsToShow) MyShowItem(dlg, *itemsToShow++);
  160.     while (*itemsToHide) MyHideItem(dlg, *itemsToHide++);
  161. }
  162.  
  163.  
  164. void Run(ExtModulesParamBlock* pb)
  165.     /* called to execute the program */
  166. {
  167.     PlottingData* v=nil;
  168.     MyStaticVars* vs = (MyStaticVars*)pb->globals;
  169.     Boolean        useCurrentGraph = true;
  170.     Handle        myMemory = nil;
  171.     long        oldDataWindow = GetCurrentWindow(dataType);
  172.  
  173.     if (TestStop()) return;
  174.  
  175.  
  176.     {    DialogData*    dlg;
  177.         short        itemHit;
  178.         short        resFile = FSpOpenResFile(GetModuleFile(), fsCurPerm);
  179.         long        x1Min = vs->x1Min, x1Max = vs->x1Max;
  180.         long        x2Min = vs->x2Min, x2Max = vs->x2Max;
  181.         long        customContourWindow = vs->customContourWindow;
  182.         long        customContourColumn = vs->customContourWindow;
  183.         Boolean        customContours;
  184.         long        dataWindow = oldDataWindow;
  185.         
  186.         if (resFile == -1) return;
  187.  
  188.         if (oldDataWindow==0)                                // if no data window
  189.         {
  190.             SysBeep(30);
  191.             MyAlert(30002);                                    // there's no data window, dammit
  192.             CloseResFile(resFile);
  193.             return;
  194.         }
  195.  
  196.         dlg = MyGetNewDialog(30000, 1, 2);
  197.         if (dlg == nil) StopExecution();
  198.         else
  199.         {
  200.             if (FrontmostWindow(drawingType) == 0 || GetCurrentGraph() == 0)    // if no drawing window or now current graph
  201.             {    useCurrentGraph = false;
  202.                 MyHiliteItem(dlg, useCurrentGraphItem, 255);        // disable
  203.             }
  204.             if (vs->customContourWindow != 0 && GetWindowType(vs->customContourWindow)==0)    // if window does not exist anymore
  205.             {    vs->customContourWindow = 0;
  206.                 vs->customContourColumn = 0;
  207.             }
  208.             else if (vs->customContourWindow)
  209.             {
  210.                 SetCurrentWindow(vs->customContourWindow);
  211.                 if (vs->customContourColumn > NrCols() || GetColType(vs->customContourColumn) == textColumn)            // if window has become smaller
  212.                     vs->customContourColumn = 1;
  213.                 SetCurrentWindow(oldDataWindow);
  214.             }
  215.             customContours = vs->customContourWindow != 0;
  216.  
  217.             MySetExtendedItem(dlg, firstLevelItem, vs->firstLevel);
  218.             MySetExtendedItem(dlg, lastLevelItem, vs->lastLevel);
  219.             MySetExtendedItem(dlg, distanceItem, vs->levelStep);
  220.  
  221.             MakeWindowPopup(dlg, dataWindowItem, dataType);
  222.             SetItemGeneral(dlg, dataWindowItem, &dataWindow);
  223.             MySetLongItem(dlg, x1FirstItem, x1Min);
  224.             MySetLongItem(dlg, x1LastItem, x1Max);
  225.  
  226.             MySetLongItem(dlg, x2FirstItem, x2Min);
  227.             MySetLongItem(dlg, x2LastItem, x2Max);
  228.  
  229.             MySetItemValue(dlg, useCurrentGraphItem, useCurrentGraph);
  230.  
  231.             MakeWindowPopup(dlg, windowItem, dataType);
  232.             if (vs->customContourWindow)
  233.                 SetItemGeneral(dlg, windowItem, &vs->customContourWindow);
  234.             MakeColumnPopup(dlg, columnItem, windowItem, 1);
  235.             if (vs->customContourColumn)
  236.                 MySetItemValue(dlg, columnItem, vs->customContourColumn);
  237.             MySetItemValue(dlg, regularContourItem, !customContours);
  238.             MySetItemValue(dlg, customContourItem, customContours);
  239.             if (FrontmostWindow(dataType)==0)                        // if no data window
  240.                 MyHiliteItem(dlg, customContourItem, 255);            // disable custom
  241.  
  242.             ShowHideItems(dlg);
  243.             MySelectItemText(dlg, x1FirstItem, 0, 0x7FFF);
  244.             MyShowDialog(dlg);
  245.             do
  246.             {
  247.                 MyModalDialog(dlg, &itemHit);
  248.  
  249.                 switch(itemHit)
  250.                 {
  251.  
  252.                 case regularContourItem:
  253.                         MySetItemValue(dlg, customContourItem, 0);
  254.                         ShowHideItems(dlg);
  255.                         break;
  256.                 case customContourItem:
  257.                         MySetItemValue(dlg, regularContourItem, 0);
  258.                         ShowHideItems(dlg);
  259.                         break;
  260.                 case helpButtonItem:
  261.                         MyAlert(30003);                    // bring up help alert
  262.                         break;
  263.                 case ok:
  264.                     {
  265.                         double    firstLevel;
  266.                         double    lastLevel;
  267.                         double    levelStep;
  268.  
  269.                         GetItemGeneral(dlg, dataWindowItem, &dataWindow);
  270.                         SetCurrentWindow(dataWindow);
  271.                         
  272.                         if (!(    MyGetExtendedItem(dlg, firstLevelItem, &firstLevel) &&
  273.                                 MyGetExtendedItem(dlg, lastLevelItem, &lastLevel) &&
  274.                                 MyGetExtendedItem(dlg, distanceItem, &levelStep) &&
  275.                                 GetColumn(dlg, x1FirstItem, &x1Min) &&
  276.                                 GetColumn(dlg, x1LastItem, &x1Max) &&
  277.                                 GetRow(dlg, x2FirstItem, &x2Min) &&
  278.                                 GetRow(dlg, x2LastItem, &x2Max)))
  279.                                     itemHit = 0;                                // if bad entry
  280.                         else if (firstLevel > lastLevel)
  281.                         {    MySelectItemText(dlg, firstLevelItem, 0, 0x7FFF);
  282.                             SysBeep(30);
  283.                             itemHit = 0;
  284.                         }
  285.                         else if (levelStep <= 1e-100 || (lastLevel-firstLevel)/levelStep > 1000)
  286.                         {    MySelectItemText(dlg, distanceItem, 0, 0x7FFF);
  287.                             SysBeep(30);
  288.                             itemHit = 0;
  289.                         }
  290.                         else if (x1Min >= x1Max)
  291.                         {    MySelectItemText(dlg, x1FirstItem, 0, 0x7FFF);
  292.                             SysBeep(30);
  293.                             itemHit = 0;
  294.                         }
  295.                         else if (x2Min >= x2Max)
  296.                         {    MySelectItemText(dlg, x2FirstItem, 0, 0x7FFF);
  297.                             SysBeep(30);
  298.                             itemHit = 0;
  299.                         }
  300.                         else
  301.                         {
  302.                             if (MyGetItemValue(dlg, regularContourItem))    // if regular contour levels
  303.                             {    vs->firstLevel = firstLevel;
  304.                                 vs->lastLevel = lastLevel;
  305.                                 vs->levelStep = levelStep;
  306.                                 vs->customContourWindow = 0;
  307.                                 vs->customContourColumn = 0;
  308.                             } else
  309.                             {    GetItemGeneral(dlg, windowItem, &vs->customContourWindow);    // get window
  310.                                 vs->customContourColumn = MyGetItemValue(dlg, columnItem);    // and column
  311.                             }
  312.                             vs->x1Min = x1Min;
  313.                             vs->x1Max = x1Max;
  314.                             vs->x2Min = x2Min;
  315.                             vs->x2Max = x2Max;
  316.                             useCurrentGraph = MyGetItemValue(dlg, useCurrentGraphItem);
  317.                         }
  318.                     }// case ok
  319.                 }//switch
  320.             }while (itemHit != ok && itemHit != cancel);
  321.             if (itemHit == cancel) StopExecution();
  322.             MyDisposeDialog(dlg);
  323.         }
  324.  
  325.  
  326.         CloseResFile(resFile);
  327.     }
  328.     if (TestStop()) return;
  329.  
  330.     SetWaitTitle("\pCalculating matrix");
  331.     {
  332.         long    nrRows = vs->x2Max - vs->x2Min + 1;
  333.         long    nrCols = vs->x1Max - vs->x1Min + 1;
  334.  
  335.         v = InitContourPlotter(nrRows, nrCols, vs->x1Min, vs->x1Max,
  336.                 vs->x2Min, vs->x2Max);
  337.         if (v==nil)
  338.         {    StopExecution();
  339.             goto done;
  340.         }
  341.  
  342.         if (!CalculateContourMatrix(MyFunction, vs, v))
  343.         {    StopExecution();
  344.             goto done;
  345.         }
  346.  
  347.     }
  348.  
  349.     SetLineStyle(1,1);
  350.     SetLineColor(0,0,0);
  351.     if (useCurrentGraph == false)
  352.     {    CreateNewGraph(vs->x1Min, vs->x1Max, vs->x2Min, vs->x2Max, 0, 0);
  353.         if (TestStop()) goto done;
  354.     }
  355.  
  356.  
  357.     DisableDrawingUpdates();                        // avoids flicker in drawing window
  358.  
  359.     {
  360.         Boolean        allLevelsDone=false;
  361.         double        level;
  362.         long        row = 1;
  363.         Boolean        regularLevels = vs->customContourWindow==0;        // true if regular levels, false if custom levels
  364.         long        levelCol = vs->customContourColumn;                // the column for custom levels
  365.         long        thickCol=0, dashCol=0, rCol=0, gCol=0, bCol=0;    // the columns for thickness, dash, rgb-values
  366.         long        nameCol=0;
  367.  
  368.  
  369.         if (regularLevels)
  370.             level = vs->firstLevel;
  371.         else                                            // parse for special additional columns
  372.         {
  373.             Boolean columnsDone = false;
  374.             long i = levelCol+1;
  375.             SetCurrentWindow(vs->customContourWindow);
  376.             while (i<=NrCols() && !columnsDone)
  377.             {
  378.                 Str255    s;
  379.                 GetColName(s, i);
  380.                 if (GetColType(i) != textColumn)
  381.                 {
  382.                     if (EqualStr255(s, "\pthickness"))
  383.                         thickCol = i;
  384.                     else if (EqualStr255(s, "\pdash"))
  385.                         dashCol = i;
  386.                     else if (EqualStr255(s, "\pr"))
  387.                         rCol = i;
  388.                     else if (EqualStr255(s, "\pg"))
  389.                         gCol = i;
  390.                     else if (EqualStr255(s, "\pb"))
  391.                         bCol = i;
  392.                     else columnsDone = true;
  393.                 }
  394.                 else if (EqualStr255(s, "\pname"))
  395.                     nameCol = i;
  396.                 else columnsDone = true;
  397.                 i += 1;
  398.             }
  399.             if (rCol == 0 || gCol == 0 || bCol == 0)        // they must all be != 0
  400.                 rCol = gCol = bCol = 0;
  401.             if (oldDataWindow) SetCurrentWindow(oldDataWindow);
  402.         }
  403.  
  404.         while (!allLevelsDone)
  405.         {
  406.             Str255    curveName;
  407.             Str255    status;
  408.             double    thick = 1.0;
  409.             double    dash = 1;
  410.             double    r=0, g=0, b=0;
  411.  
  412.             if (!regularLevels)
  413.             {
  414.                 SetCurrentWindow(vs->customContourWindow);
  415.                 while (!TestData(row, levelCol))
  416.                 {    if (row >= NrRows())
  417.                     {    allLevelsDone = true;
  418.                         break;                                // if all done
  419.                     }
  420.                     row += 1;
  421.                 }
  422.                 if (allLevelsDone) break;
  423.                 level = GetData(row, levelCol);
  424.                 if (thickCol != 0 && TestData(row, thickCol))
  425.                     thick = GetData(row, thickCol);
  426.                 if (dashCol != 0 && TestData(row, dashCol))
  427.                     dash = GetData(row, dashCol);
  428.                 if (rCol != 0 && TestData(row, rCol) && TestData(row, gCol) && TestData(row, bCol))
  429.                 {    r = GetData(row, rCol);
  430.                     g = GetData(row, gCol);
  431.                     b = GetData(row, bCol);
  432.                 }
  433.                 if (nameCol != 0)
  434.                     GetCell(curveName, row, nameCol);
  435.                 row += 1;
  436.                 if (row > NrRows()) allLevelsDone = true;
  437.  
  438.                 if (oldDataWindow) SetCurrentWindow(oldDataWindow);
  439.             }
  440.  
  441.             if (nameCol == 0)
  442.                 NumberToStr255(level, curveName, 0, 3);
  443.             Concat2(status, "\plevel: ", curveName);
  444.  
  445.             SetLineStyle(thick, dash);
  446.             SetLineColor(r,g,b);
  447.  
  448.             SetWaitTitle(status);
  449.             OpenCurve(curveName);
  450.             if (!DrawContour(level, v)) goto done;
  451.             CloseCurve();
  452.             SetLineStyle(1,1);
  453.             SetLineColor(0,0,0);
  454.             if (regularLevels)
  455.             {    level += vs->levelStep;
  456.                 allLevelsDone = level > vs->lastLevel;
  457.             }
  458.  
  459.         }
  460.     }
  461.  
  462.  
  463.  
  464. done:                                                // clean up
  465.     DisposeContourPlotter(v);                        // does nothing if v==nil
  466.     if (oldDataWindow) SetCurrentWindow(oldDataWindow);
  467.     if (myMemory != nil) DisposeHandle(myMemory);
  468. }
  469.  
  470. /***************************************************************************************/
  471.  
  472. void CleanUp (ExtModulesParamBlock* pb)
  473.     /* called when your code resource is not needed anymore */
  474.     /* in most cases, this function can be empty */
  475. {
  476. }
  477.  
  478.  
  479. /***************************************************************************************/
  480.                         /* for functions, not used here: */
  481. /***************************************************************************************/
  482.  
  483. void InitializeFunc (
  484.                 Boolean* const hasDerivatives,    /* set to true if you define the function Derivatives to calculate the partial derivatives of your parameters */
  485.                 Str255 descr1stLine,            /* string 1 to appear in parameter window */
  486.                 Str255 descr2ndLine,            /* string 2 to appear in parameter window */
  487.                 short* const numberOfParams,    /* the number of parameters of your function */
  488.                 DefaultParamInfo* const a0,            /* the default names, values etc. of your parameters */
  489.                 ExtModulesParamBlock* pb)        /* can be ignored in most cases */
  490. {}
  491.  
  492. void Func (        double x,                        /* the x-value */
  493.                 ParamArray a,                    /* the parameters */
  494.                 double* const y,                /* the y-value to be returned */
  495.                 ExtModulesParamBlock* pb)        /* can be ignored in most cases */
  496. {}
  497.  
  498. void Derivatives(double x,                        /* the x-value */
  499.                 ParamArray a,                    /* the parameters */
  500.                 ParamArray dyda,                /* the derivatives to be returned */
  501.                 ExtModulesParamBlock* pb)
  502. {}
  503. short Check(short paramNo,                        /* the parameter that was changed */
  504.                 DefaultParamInfo* const a0,            /* the default names, values etc of the paramters */
  505.                 ExtModulesParamBlock* pb)
  506. {paramNo--;/*the array a0 is indexed from zero. Decrement paramNo so that it corresponds to the inices of a0*/
  507.     return ok;
  508. }
  509. void First (    ParamArray a,                    /* the new parameters */
  510.                 ExtModulesParamBlock* pb)
  511. {}
  512. void Last (ExtModulesParamBlock* pb)
  513. {}